package org.example.demo.module

import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.snapshots.SnapshotStateList
import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.screenModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.example.demo.bean.ChatMessage
import org.example.demo.chat.ext.isFinished
import org.example.demo.chat.request.AdditionalMessage
import org.example.demo.chat.request.ChatLaunchRequestParam
import org.example.demo.chat.response.ChatLaunchResponse
import org.example.demo.chat.response.ChatMsgDetailResponse
import org.example.demo.chat.response.ChatRetrieveResponse
import org.example.demo.util.BOT_CHAT
import org.example.demo.util.BOT_CHAT_MESSAGE_LIST
import org.example.demo.util.BOT_CHAT_RETRIEVE
import org.example.demo.util.HEADER

class ChatModule(
    private val botId: String
) : ScreenModel {

    private val _editorText = mutableStateOf("")
    val editorText: State<String> = _editorText

    private val _chatMsgList = mutableStateListOf<ChatMessage>()
    val chatMsgList: SnapshotStateList<ChatMessage> = _chatMsgList

    fun onTextChanged(text: String) {
        _editorText.value = text
    }

    fun onSendClick(content: String) {
        if (content.isBlank()) {
            return
        }
        onTextChanged("")
        _chatMsgList.removeAll { it.followUp }
        _chatMsgList.add(ChatMessage(isSelf = true, followUp = false, reflectTime = 0, content))
        screenModelScope.launch(Dispatchers.IO) {
            requestChatApi(content)
        }
    }

    private suspend fun requestChatApi(content: String) {
        val result = HttpService.post<ChatLaunchResponse>(
            BOT_CHAT,
            HEADER,
            ChatLaunchRequestParam(
                botId,
                "admin",
                false,
                listOf(AdditionalMessage(content, "text", "user"))
            )
        )
        var success = false
        screenModelScope.launch(Dispatchers.IO) {
            while (!success) {
                delay(1000)
                val retrieveData = requestRetrieveApi(result.data?.conversationId, result.data?.id)
                success = retrieveData?.isFinished() ?: true
                if (success) {
                    val detailData = requestMsgListApi(
                        retrieveData?.data?.conversationId,
                        retrieveData?.data?.id
                    )
                    detailData?.data?.filter { it.type != "verbose" && !it.content.isNullOrBlank() }
                        ?.map {
                            ChatMessage(
                                false,
                                it.type == "follow_up",
                                (it.updatedAt ?: 0) - (it.createdAt ?: 0),
                                it.content ?: ""
                            )
                        }
                        ?.let {
                            _chatMsgList.addAll(it)
                        }
                    println(detailData)
                }
            }
        }
    }

    private suspend fun requestRetrieveApi(
        conversationId: String?,
        chatId: String?
    ): ChatRetrieveResponse? {
        if (conversationId == null || chatId == null) {
            return null
        }
        val result = HttpService.get<ChatRetrieveResponse>(
            BOT_CHAT_RETRIEVE,
            HEADER,
            mapOf(
                "conversation_id" to conversationId,
                "chat_id" to chatId
            )
        )
        return result
    }

    private suspend fun requestMsgListApi(
        conversationId: String?,
        chatId: String?
    ): ChatMsgDetailResponse? {
        if (conversationId == null || chatId == null) {
            return null
        }
        val result = HttpService.get<ChatMsgDetailResponse>(
            BOT_CHAT_MESSAGE_LIST,
            HEADER,
            mapOf(
                "conversation_id" to conversationId,
                "chat_id" to chatId
            )
        )
        return result
    }
}